package visualizer.client.algorithms.sBst;

import visualizer.client.algorithms.AlgoResult;
import visualizer.client.algorithms.Algorithm;
import visualizer.client.bst.BNode;
import visualizer.client.bst.BinaryTree;

import java.util.ArrayList;
import java.util.List;

import static visualizer.client.utils.VisualizerUtils.DEFAULT_OUTER_COLOR;

/**
 * User: DDovzhenko
 * Date: 06.01.14
 * Time: 17:17
 */
public class SBSTAddingAlgorithm implements Algorithm {
    private BinaryTree tree;
    private List<AlgoResult> results = new ArrayList<AlgoResult>();
    boolean isAdded;

    @Override
    public AlgoResult performAlgorithmToStep(BinaryTree tree, int step, int inputValue) {
        return results.get(step);
    }

    @Override
    public int getStepsCount(BinaryTree binaryTree, int inputValue) {
        results.clear();
        isAdded = true;
        results.add(new AlgoResult(binaryTree.copyTree(false), " Вставка узла с ключом " + inputValue + ". Сначала выполним обычную вставку нового узла в дерево, а потом переместим его в корень."));
        tree = binaryTree.copyTree(false);
        insert(createNewNode(inputValue));
        results.add(new AlgoResult(tree, isAdded ? "Новый узел успешно добавлен" : "Узел с таким ключом существует и перемещен в корень дерева"));
        return results.size();
    }

    private BNode createNewNode(int inputValue) {
        BNode newNode = new BNode(inputValue);
        newNode.setInnerColor("lightgreen");
        newNode.setOuterColor("green");
        return newNode;
    }

    private void insert(BNode newNode) {
        BNode treeRoot = tree.getRoot();
        if (treeRoot == null) {
            tree.setRootNode(newNode);
        } else {
            insertToBST(treeRoot, newNode);
            if (isAdded) {
                results.add(new AlgoResult(tree.copyTree(true), "Новый узел добавлен, теперь переместим его в корень дерева"));
            } else {
                results.add(new AlgoResult(tree.copyTree(true), "Узел уже существует, теперь переместим его в корень дерева"));
            }
            SplayBSTUtils.splay(tree, newNode.getValue(), results);
        }
    }

    private void insertToBST(BNode root, BNode newNode) {
        root.setOuterColor("red");
        if (root.getValue().equals(newNode.getValue())) {
            root.setInnerColor("lightgreen");
            root.setOuterColor("green");
            isAdded = false;
            return;
        }
        if (newNode.getValue() < root.getValue()) {
            results.add(new AlgoResult(tree.copyTree(true), "Сравниваем ключи в узлах: " + newNode.getValue() + " < " + root.getValue() + ", обрабатываем левое поддерево"));
            if (root.getLeftBNode() == null) {
                results.add(new AlgoResult(tree.copyTree(true), "Здесь нет узла, вставляем новый узел на это место"));
                root.setOuterColor(DEFAULT_OUTER_COLOR);
                root.setLeftBNode(newNode);
            } else {
                root.setOuterColor(DEFAULT_OUTER_COLOR);
                insertToBST(root.getLeftBNode(), newNode);
            }
        } else {
            results.add(new AlgoResult(tree.copyTree(true), "Сравниваем ключи в узлах: " + newNode.getValue() + " > " + root.getValue() + ", обрабатываем правое поддерево"));
            if (root.getRightBNode() == null) {
                results.add(new AlgoResult(tree.copyTree(true), "Здесь нет узла, вставляем новый узел на это место"));
                root.setOuterColor(DEFAULT_OUTER_COLOR);
                root.setRightBNode(newNode);
            } else {
                root.setOuterColor(DEFAULT_OUTER_COLOR);
                insertToBST(root.getRightBNode(), newNode);
            }
        }
    }
}
